#include "table_view2.h"

namespace
{

QString create_random_length_string(int max_length)
{
    const int length = qrand() % max_length;
    return QString(length, 'X');
}

}

table_view2::table_view2(int min_row_to_show, int min_col_to_show, QWidget *parent)
    : QTableView      (parent)
    , model_          (new QStandardItemModel(this))
    , min_row_to_show_(min_row_to_show)
    , min_col_to_show_(min_col_to_show)
{
    setModel(model_);

//    setSizePolicy(QSizePolicy::Fixed           , QSizePolicy::Fixed           );
    setSizePolicy(QSizePolicy::Minimum         , QSizePolicy::MinimumExpanding        );
//    setSizePolicy(QSizePolicy::Maximum         , QSizePolicy::Maximum         );
//    setSizePolicy(QSizePolicy::Preferred       , QSizePolicy::Preferred       );
//    setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding);
//    setSizePolicy(QSizePolicy::Expanding       , QSizePolicy::Expanding       );
//    setSizePolicy(QSizePolicy::Ignored         , QSizePolicy::Ignored         );

}

void table_view2::create_table(int row, int col)
{
    clear_table();
    if (model_->rowCount() > 0 || model_->columnCount() > 0)
        return;


    for (int i = 0; i < col; ++i)
    {
        QStandardItem *header_item = new QStandardItem("header" + QString::number(qrand()%1000000));
//        QStandardItem *header_item = new QStandardItem("h");
        model_->setHorizontalHeaderItem(i, header_item) ;
    }

    for (int i = 0; i < row; ++i)
    {
        QList<QStandardItem*> items;
        for (int j = 0; j < col; ++j)
        {
            items << new QStandardItem(create_random_length_string(j % 2 == 0 ? 5 : 10));
        }

        model_->appendRow(items);
    }
}

void table_view2::add_row()
{
    QList<QStandardItem*> items;
    for (int i = 0; i < model_->columnCount(); ++i)
        items << new QStandardItem("Ole-ole-ole");

    model_->appendRow(items);
    auto_resize();
}

void table_view2::del_row()
{
    model_->removeRow(0);
    auto_resize();
}

void table_view2::add_col()
{
    QList<QStandardItem*> items;
    for (int i = 0; i < model_->rowCount(); ++i)
        items << new QStandardItem("Ole-ole-ole");

    model_->appendColumn(items);

    QStandardItem *header_item = new QStandardItem("header" + QString::number(qrand()%1000000));
    model_->setHorizontalHeaderItem(model_->columnCount() - 1, header_item) ;
    auto_resize();
}

void table_view2::del_col()
{
    model_->removeColumn(0);
    auto_resize();
}

void table_view2::auto_resize()
{
    horizontalHeader()->setStretchLastSection(false);
    verticalHeader  ()->setStretchLastSection(false);

    resizeRowsToContents();
    resizeColumnsToContents();

    horizontalHeader()->setStretchLastSection(true);
    verticalHeader  ()->setStretchLastSection(true);

    setHorizontalScrollBarPolicy(model()->columnCount() > min_col_to_show_
                                 ? Qt::ScrollBarAlwaysOn
                                 : Qt::ScrollBarAlwaysOff);

    setVerticalScrollBarPolicy(model()->rowCount() > min_row_to_show_
                               ? Qt::ScrollBarAlwaysOn
                               : Qt::ScrollBarAlwaysOff);

    const auto content_with_header_width = min_width_for_content() + verticalHeader()->frameGeometry().width();
    const auto table_width = verticalScrollBar()->isVisible()
            ? frameWidth() + content_with_header_width + 1 + verticalScrollBar()->frameGeometry().width()
            : 2*frameWidth() + content_with_header_width;

    setMinimumWidth(table_width);

    const auto content_with_header_height = min_height_for_content() + horizontalHeader()->frameGeometry().height();
    const auto table_height = horizontalScrollBar()->isVisible()
            ? frameWidth() + content_with_header_height + 1 + horizontalScrollBar()->frameGeometry().height()
            : 2*frameWidth() + content_with_header_height;

    setMinimumHeight(table_height);

    updateGeometry();

    auto w = parentWidget();
    while (w)
    {
        w->adjustSize();
        w = w->parentWidget();
    }
}

void table_view2::clear_table()
{
    model_->clear();
}

void table_view2::print_sizes()
{
#if 0
//    qDebug() << "---------------VERTICAL SIZES---------------";
//    qDebug() << "horizontalHeader()->sizeHint().height() :" << horizontalHeader()->sizeHint().height();
//    qDebug() << "horizontalHeader()->frameGeometry.height:" << horizontalHeader()->frameGeometry().height();
//    qDebug() << "horizontalHeader()->geometry.height()   :" << horizontalHeader()->geometry().height();
//    qDebug() << "horizontalHeader()->sectionSize(0)      :" << horizontalHeader()->sectionSize(0);
//    qDebug() << "verticalHeader()->sectionSize(0)        :" << verticalHeader()->sectionSize(0);
//    qDebug() << "2 * frameWidth()                        :" << 2 * frameWidth();
//    qDebug() << "verticalHeader()->length()              :" << verticalHeader()->length();

//    int height = 0;
//    for(int i = 0; i < model()->rowCount(); ++i)
//        height += verticalHeader()->sectionSize(i);
//    qDebug() << "sum of verticalHeader()->sectionSize(i) :" << height;

//    qDebug() << "horizontalScrollBar()->size()           :" << horizontalScrollBar()->size();
//    qDebug() << "horizontalScrollBar()->frameSize()      :" << horizontalScrollBar()->frameSize();
//    qDebug() << "horizontalScrollBar()->geometry().size():" << horizontalScrollBar()->geometry().size();
//    qDebug() << "horizontalScrollBar()->frameGeometry()  :" << horizontalScrollBar()->frameGeometry();
//    qDebug() << "horizontalScrollBar()->sizeHint()       :" << horizontalScrollBar()->sizeHint();

//    qDebug() << "frameGeometry()                         :" << frameGeometry();
//    qDebug() << "geometry()                              :" << geometry();


    qDebug() << mapToGlobal(frameGeometry().topLeft()) << frameGeometry().height();
    qDebug() << mapToGlobal(geometry().topLeft()) << geometry().height();
    qDebug() << mapToGlobal(horizontalHeader()->frameGeometry().topLeft()) << horizontalHeader()->frameGeometry().height();
    qDebug() << mapToGlobal(horizontalHeader()->geometry().bottomLeft()) << horizontalHeader()->geometry().height(); // equal previous

    qDebug() << mapToGlobal(viewport()->frameGeometry().topLeft()) << viewport()->frameGeometry().height();
    qDebug() << mapToGlobal(viewport()->geometry().bottomLeft()) << viewport()->geometry().height();  // equal previous

    qDebug() << horizontalScrollBar()->mapToGlobal(horizontalScrollBar()->frameGeometry().topLeft()) << horizontalScrollBar()->frameGeometry().height();
    qDebug() << horizontalScrollBar()->mapToGlobal(horizontalScrollBar()->geometry().bottomLeft()) << horizontalScrollBar()->geometry().height();  // equal previous

//    qDebug() << geometry();
//    qDebug() << horizontalScrollBar()->frameGeometry();
//    qDebug() << frameGeometry();
#endif
}

QSize table_view2::sizeHint() const
{
    return minimumSize();
}

void table_view2::resizeEvent(QResizeEvent *e)
{
//    if(horizontalScrollBar()->minimum() < horizontalScrollBar()->maximum())
//        horizontalScrollBar()->show();
//    else
//        horizontalScrollBar()->hide();

    QTableView::resizeEvent(e);
}

int table_view2::sizeHintForColumn(int column) const
{
    if (!model())
        return -1;

    ensurePolished();

    int hint = 0;
    const QStyleOptionViewItemV4 option = static_cast<QStyleOptionViewItemV4>(viewOptions());
    for(int i = 0; i < model()->rowCount(); ++i)
    {
        const auto index = model()->index(i, column);
        hint = qMax(hint, itemDelegate(index)->sizeHint(option, index).width());
    }

    return showGrid() ? hint + 1 : hint;
}

int table_view2::sizeHintForRow(int /*row*/) const
{
    if (!model())
        return -1;

    return 20;
}

int table_view2::min_width_for_content() const
{
    const auto h_header = horizontalHeader();
    const auto size = qMin(h_header->count(), min_col_to_show_);

    int width = 0;
    for(int i = 0; i < size; ++i)
        width += qMax(h_header->sectionSizeHint(i), sizeHintForColumn(i));

    return width;
}

int table_view2::min_height_for_content() const
{
    const auto v_header = verticalHeader();
    const auto size = qMin(v_header->count(), min_row_to_show_);

    int height = 0;
    for(int i = 0; i < size; ++i)
        height += qMax(v_header->sectionSizeHint(i), sizeHintForRow(i));

    return height;
}











